﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XcoAppSpaces.Core;
using XcoAppSpaces.Core.Ports;
using System.Threading;
using NUnit.Framework;
using XcoAppSpaces.Serialization.Json;

namespace test.XcoAppSpaces.Core
{
	[TestFixture]
	public class testDirectPortHosting
	{
		[Test]
		public void TestPublishPort()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8000"),
				space2 = new XcoAppSpace("tcp.port=8001"))
			{
				var port = new Port<int>();
				space1.RunWorker(port);

				var remotePort = space2.ConnectWorker<Port<int>>(Environment.MachineName + ":8000");
				
				remotePort.Post(1);
				Assert.AreEqual(1, port.Receive(1000).Result);
			}
		}

		[Test]
		public void TestPublishPortShort()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8001"),
				space2 = new XcoAppSpace("tcp.port=8002"))
			{
				int received = 0;
				space1.Run<int>(msg => received = msg);

				var remotePort = space2.Connect<int>("localhost:8001");
				remotePort.Post(1);

				Thread.Sleep(500);
				Assert.AreEqual(1, received);
			}
		}

		[Test]
		public void TestPublishPortWithName()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8000"),
				space2 = new XcoAppSpace("tcp.port=8001"))
			{
				var port = new Port<int>();
				space1.RunWorker(port, "myIntPort");

				var remotePort = space2.ConnectWorker<Port<int>>(Environment.MachineName + ":8000/myIntPort");

				remotePort.Post(1);
				Assert.AreEqual(1, port.Receive(1000).Result);
			}
		}

		[Test]
		public void TestPublishPortShortWithName()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8001"),
				space2 = new XcoAppSpace("tcp.port=8002"))
			{
				int received = 0;
				space1.Run<int>("myport", msg => received = msg);

				var remotePort = space2.Connect<int>("localhost:8001/myport");
				remotePort.Post(1);

				Thread.Sleep(500);
				Assert.AreEqual(1, received);
			}
		}

		[Test]
		public void TestPublishPortSet()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8000"),
				space2 = new XcoAppSpace("tcp.port=8001"))
			{
				var portSet = new PortSet<int, string>();
				space1.RunWorker(portSet);

				var remotePortSet = space2.ConnectWorker<PortSet<int, string>>(Environment.MachineName + ":8000");

				remotePortSet.Post(1);
				remotePortSet.Post("test");
				Assert.AreEqual(1, portSet.P0.Receive(1000).Result);
				Assert.AreEqual("test", portSet.P1.Receive(1000).Result);
			}
		}

		[Test]
		public void TestPublishPortSetWithName()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8000"),
				space2 = new XcoAppSpace("tcp.port=8001"))
			{
				var portSet = new PortSet<int, string>();
				space1.RunWorker(portSet, "myPortSet");

				var remotePortSet = space2.ConnectWorker<PortSet<int, string>>(Environment.MachineName + ":8000/myPortSet");

				remotePortSet.Post(1);
				remotePortSet.Post("test");
				Assert.AreEqual(1, portSet.P0.Receive(1000).Result);
				Assert.AreEqual("test", portSet.P1.Receive(1000).Result);
			}
		}

		[Test]
		public void TestPublishPortWithResponse()
		{
			using (XcoAppSpace space1 = new XcoAppSpace("tcp.port=8001"),
				space2 = new XcoAppSpace("tcp.port=8002"))
			{
				space1.Run<Port<string>>(msg => msg.Post("hello"));

				var remotePort = space2.Connect<Port<string>>("localhost:8001");
				string received = null;
				var responsePort = Port.WithReceiver<string>(msg => received = msg);
				remotePort.Post(responsePort);

				Thread.Sleep(500);
				Assert.AreEqual("hello", received);
			}
		}
	}
}
